﻿using System;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Configuration;
using System.Data.Linq;
using SacNetUG.Areas.Forum.Models;
using SacNetUG.Areas.Forum.Models.Abstract;
using SacNetUG.Areas.Forum.Models.Concrete;

namespace SacNetUG.Areas.Forum.Controllers
{
    //[Authorize(Roles="moderator"]
    public class ModeratorController : Controller
    {
        private IPostsRepository postsRepository;
        public ModeratorController()
        {
            string connString = WebConfigurationManager.ConnectionStrings["SacNetUGConnectionString"].ToString();
            postsRepository = new SqlPostsRepository(connString);
        }

        public ActionResult Home()
        {
            return RedirectToAction("AllSubjectsAndPostsForModerator");
        }
        
        [HttpGet]
        public ViewResult AllSubjectsAndPostsForModerator()
        {
            ViewData["AllSubjectsAndResultingPosts"] = "Technical Forum:  All Subjects and Responses";
            return View(postsRepository.Posts.ToList());
        }

        [HttpGet]
        public ViewResult EditPost(string id)
        {
            int postIDToEdit = int.Parse(id);
            var postToEdit = postsRepository.Posts.First(p => p.PostID == postIDToEdit);
            return View(postToEdit);
        }

        [HttpPost]
        public ActionResult EditPost(Post theModifiedPost)
        {
            if (ModelState.IsValid)
            {
                postsRepository.SaveModifiedPost(theModifiedPost);
                TempData["SaveModifiedPostMessage"] = "Your modifications to the selected post have been saved";
                return RedirectToAction("AllSubjectsAndPostsForModerator");
            }
            else    //some error happened
            {
                TempData["SaveModifiedPostMessage"] = "some error here in trying to save changes";
                return View(theModifiedPost);
            }
        }

        public ActionResult DeletePost(string id)
        {
            int postIDToDelete = int.Parse(id);
            var postToDelete = postsRepository.Posts.First(p => p.PostID == postIDToDelete);
            postsRepository.DeleteSelectedPost(postToDelete);
            TempData["DeletePostMessage"] = "Your selected post has been deleted";
            return RedirectToAction("AllSubjectsAndPostsForModerator");
        }

        public ViewResult FlaggedItems()
        {
            ViewData["FlaggedItems"] = "Forum Moderator:  All Flagged Items; to be approved or deleted";

            string connString = WebConfigurationManager.ConnectionStrings["SacNetUGConnectionString"].ToString();
            DataContext postsContext = new DataContext(connString);

            var flaggedItems = (from p in postsContext.GetTable<Post>()
                               where p.Flagged == true
                               orderby p.DatePosted descending
                               select p).ToList();

            return View(flaggedItems);
          }

        public ViewResult FlaggedThenApprovedItems()
        {
            ViewData["FlaggedThenApprovedItems"] = "Forum Moderator:  All Flagged, Then Approved Items";

            string connString = WebConfigurationManager.ConnectionStrings["SacNetUGConnectionString"].ToString();
            DataContext postsContext = new DataContext(connString);

            var flaggedThenApprovedItems = (from p in postsContext.GetTable<Post>()
                                where p.FlaggedThenApproved == true
                                orderby p.DatePosted descending
                                select p).ToList();

            return View(flaggedThenApprovedItems);
        }

        public ActionResult DeleteFlagged(string id)
        {
            int postIDToDelete = int.Parse(id);
            var postToDelete = postsRepository.Posts.First(p => p.PostID == postIDToDelete);
            postsRepository.DeleteSelectedPost(postToDelete);
            TempData["DeletePostMessage"] = "The previously flagged post has been deleted";
            return RedirectToAction("AllSubjectsAndPostsForModerator");
        }

        public ActionResult ApproveFlagged(string id)
        {
            int postIDToApprove = int.Parse(id);
            var postToApprove = postsRepository.Posts.First(p => p.PostID == postIDToApprove);
            postToApprove.FlaggedThenApproved = true;
            postToApprove.Flagged = false;
            postsRepository.ApproveFlaggedSubjectOrPost(postToApprove);
            TempData["ApproveFlaggedMessage"] = "The previously flagged post has been marked as approved";
            return RedirectToAction("AllSubjectsAndPostsForModerator");
        }

        public ViewResult DataIntegrity()
        {
            return View();
        }
        
        public ViewResult CheckIntegrity()
        {
            //get the list of subjects
            string connString = WebConfigurationManager.ConnectionStrings["SacNetUGConnectionString"].ToString();
            DataContext postsContext = new DataContext(connString);

            var allSubjects = (from p in postsContext.GetTable<Post>()
                               where p.IsTheInitialPost == true && p.Flagged == false
                               orderby p.DatePosted descending
                               select p).ToList();

            //go through the list of subjects, verifying/correcting number of posts to each subject
            int subjectsCount = allSubjects.Count();
            int allPostsToAllSubjectsCount = 0;     //this will finally be used to check the integrity of the Posts table (possibly, some posts have no subject)

            foreach (Post subject in allSubjects)
            {
                int subjectID = subject.PostID;
                int numberOfPosts = subject.NumberOfPosts;

                var allPostsToSubject = (from p in postsContext.GetTable<Post>()
                                         where p.PostedTo == subjectID
                                         select p).ToList();

                if (!(numberOfPosts == allPostsToSubject.Count))                //count of posts to this subject is incorrect
                {
                    subject.NumberOfPosts = allPostsToSubject.Count;            //change the count
                    if (ModelState.IsValid)
                    {
                        postsRepository.SaveModifiedPost(subject);              //save the modified Subject
                        allPostsToAllSubjectsCount += subject.NumberOfPosts;    //increment total number of posts to Subjects (after modification)
                    }
                    else    //some error happened
                    {
                        TempData["SaveModifiedSubjectMessage"] = "some error in trying to save changes to Number of Posts to the Subject";
                        return View();
                    }
                }
                else
                {
                    allPostsToAllSubjectsCount += allPostsToSubject.Count;    //increment total number of posts to Subjects (no modification)
                }
            }
            //check to see that the count of all posts (which are not subjects) is equal to the sum of those assigned to subjects
            //this is necessary because a subject may get deleted without deleting the posts to this subject

            var allPostsToSubjects = (from p in postsContext.GetTable<Post>()
                                      where p.IsTheInitialPost == false 
                                      select p).ToList();

            //report via the View the results of running this count check of integrity in the forum part of the database (Post table only)
            if (!(allPostsToSubjects.Count == allPostsToAllSubjectsCount))   
                TempData["DataIntegrityReport"] = "Post table has lost integrity;  some posts probably no longer have an existing subject";
            else
                TempData["DataIntegrityReport"] = "Post table has integrity;  all posts have an existing subject";
            int excessPosts = (allPostsToSubjects.Count - allPostsToAllSubjectsCount);

            ViewData["excessposts"] = excessPosts;
            return View(); 
        }
    }
}
